import { Text, useMessage } from 'alemonjs'
import { ioredis, battle, skill_list, drop_list, user } from '@src/db'
import { addIntoBag, setUserStatus } from '../tools'

/**
 * 检查同阵营是否全部出招，并返回出招信息文本
 * @param battle_id 战斗id
 * @param battle_camp 阵营
 * @returns Promise<{ allReady: boolean, reply: string }>
 */
export async function getCampActionStatus(
  battle_id: number,
  battle_camp: number,
  e
): Promise<{ reply: string }> {
  const campMembers = await battle.findAllValues({
    where: { battle_id, battle_camp }
  })
  const allIndexes = campMembers.map(m => m.battle_index)
  const allNames = campMembers.map(m => m.name || `成员${m.battle_index}`)
  const actionKeys = allIndexes.map(
    idx => `fantasy:battle:${battle_id}:${battle_camp}:${idx}:action`
  )
  const actions = await ioredis.mget(...actionKeys)
  const allReady = actions.every(a => a && a !== '')

  let reply = '\n'
  if (!allReady) {
    for (let i = 0; i < allIndexes.length; i++) {
      reply += `[${allNames[i]}] ${actions[i] ? actions[i] : ''}\n`
    }
  } else {
    reply = await battleRound(battle_id, e)
  }
  return { reply }
}

/**
 * 执行战斗回合
 * @param battle_id 战斗id
 * @returns Promise<string>
 * */
export async function battleRound(battle_id: number, e): Promise<string> {
  // 查询所有战斗成员信息
  const battleInfo = await battle.findAllValues({ where: { battle_id } })
  // 获取当前回合数
  const battleRound =
    (await ioredis.get(`fantasy:battle:${battle_id}:round`)) || 0
  let txt_return = `\n【战斗回合：${Number(battleRound) + 1}】`

  // 获取所有成员的阵营和索引
  const battleCampIndex = battleInfo.map(m => ({
    camp: m.battle_camp,
    index: m.battle_index
  }))
  // 所有成员加入待行动队列
  let battleQueue = battleCampIndex.map(({ camp, index }) => ({ camp, index }))

  // 行动循环
  while (battleQueue.length > 0) {
    // 批量读取所有成员的详细信息
    const infoKeys = battleQueue.map(
      ({ camp, index }) => `fantasy:battle:${battle_id}:${camp}:${index}:info`
    )
    const allMemberInfos = await Promise.all(
      infoKeys.map(key => ioredis.hgetall(key))
    )

    // 每次循环都重新提取速度并排序
    battleQueue.sort((a, b) => {
      const idxA = battleCampIndex.findIndex(
        x => x.camp === a.camp && x.index === a.index
      )
      const idxB = battleCampIndex.findIndex(
        x => x.camp === b.camp && x.index === b.index
      )
      const speedA = Number(allMemberInfos[idxA]?.speed || 0)
      const speedB = Number(allMemberInfos[idxB]?.speed || 0)
      return speedB - speedA
    })

    // 取出当前速度最快的成员
    const { camp, index } = battleQueue[0]
    const actionKey = `fantasy:battle:${battle_id}:${camp}:${index}:action`
    let action = await ioredis.get(actionKey)
    const targetKey = `fantasy:battle:${battle_id}:${camp}:${index}:target`

    // 读取当前成员信息
    const playerKey = `fantasy:battle:${battle_id}:${camp}:${index}:info`
    const playerInfo = (await ioredis.hgetall(playerKey)) || {}

    // 如果成员当前hp小于等于0
    if (Number(playerInfo.hp) <= 0) {
      txt_return += `\n[${playerInfo.name}]已倒地\n——————————————`

      // 回合末，所有冷却中技能回合数-1（自动过期，无需手动清除）
      const pattern = `fantasy:battle:${battle_id}:${camp}:${index}:skill_cd:*`
      const keys = await ioredis.keys(pattern)
      for (const cdKey of keys) {
        const cdLeft = await ioredis.ttl(cdKey)
        if (cdLeft > 1) {
          await ioredis.expire(cdKey, cdLeft - 1)
        }
      }

      // 从队列中移除
      battleQueue.shift()

      // 清除该成员的行动指令
      await ioredis.del(actionKey)

      continue
    }

    if (!action || action === '') {
      // 从uid是否小于10判断是不是敌人阵营
      const isEnemy = Number(playerInfo.uid) < 10
      // 如果是，读取敌人技能内容
      if (isEnemy) {
        // 读取敌人技能列表
        const enemySkills = await battle.findOneValue({
          where: { battle_id, battle_camp: camp, battle_index: index }
        })
        if (enemySkills) {
          // 解析技能列表
          const skillList =
            typeof enemySkills.base_skill === 'string'
              ? JSON.parse(enemySkills.base_skill || '[]')
              : Array.isArray(enemySkills.base_skill)
                ? enemySkills.base_skill
                : []

          // 检查每个技能是否在冷却且mp足够
          const availableSkills: string[] = []
          for (const skillName of skillList) {
            const skillCdKey = `fantasy:battle:${battle_id}:${camp}:${index}:skill_cd:${skillName}`
            const cdLeft = await ioredis.ttl(skillCdKey)
            // 查询技能信息获取mp消耗
            const skillInfo = await skill_list.findOneValue({
              where: { name: skillName }
            })
            const mpCost = skillInfo?.mp_cost || 0
            const currentMp = Number(playerInfo.mp) || 0
            if ((cdLeft <= 0 || cdLeft === -2) && currentMp >= mpCost) {
              availableSkills.push(skillName)
            }
          }

          // 如果有可用技能，随机选择一个写成 技能:技能名
          if (availableSkills.length > 0) {
            const randomSkill =
              availableSkills[
                Math.floor(Math.random() * availableSkills.length)
              ]
            await ioredis.set(actionKey, `技能:${randomSkill}`)
          } else {
            // 如果没有可用技能，普攻写入redis
            await ioredis.set(actionKey, '普攻')
          }
        } else {
          // 没有技能，普攻写入redis
          await ioredis.set(actionKey, '普攻')
        }

        // 读取目标
        const enemyTargetKey = `fantasy:battle:${battle_id}:${camp}:${index}:target`
        const enemyTarget = await ioredis.get(enemyTargetKey)
        // 如果没有目标，则随机选择一个存活的敌人作为目标
        if (!enemyTarget || enemyTarget === '') {
          // 获取敌方阵营
          const enemyCamp = Number(camp) === 1 ? 2 : 1
          // 查询敌方存活成员
          const enemyKeys = Array.from(
            { length: 6 },
            (_, i) => `fantasy:battle:${battle_id}:${enemyCamp}:${i + 1}:info`
          )
          const enemyInfos = await Promise.all(
            enemyKeys.map(key => ioredis.hgetall(key))
          )
          const aliveEnemies = enemyInfos
            .map((info, idx) => ({ hp: Number(info.hp) || 0, pos: idx + 1 }))
            .filter(obj => obj.hp > 0)
            .map(obj => obj.pos)
          // 写入redis
          if (aliveEnemies.length > 0) {
            const randomTarget =
              aliveEnemies[Math.floor(Math.random() * aliveEnemies.length)]
            await ioredis.set(enemyTargetKey, String(randomTarget))
          } else {
            // 如果没有存活目标，则不设置目标
            await ioredis.del(enemyTargetKey)
          }
        }
      }
    }

    // 重新读取行动
    action = await ioredis.get(actionKey)
    // 重新读取目标
    const currentTarget = (await ioredis.get(targetKey)) || '无目标'

    if (action?.startsWith('普攻')) {
      // 在此处添加普攻的具体逻辑
      // 在此处添加普攻的具体逻辑
      // 在此处添加普攻的具体逻辑

      txt_return += `\n【${playerInfo.name}】普通攻击→[${currentTarget}]`

      // 目标角色信息
      const enemyCamp = Number(camp) === 1 ? 2 : 1
      const enemyKey = `fantasy:battle:${battle_id}:${enemyCamp}:${currentTarget}:info`
      const enemyInfo = (await ioredis.hgetall(enemyKey)) || {}

      // 检查目标是否倒地
      if (Number(enemyInfo.hp) <= 0) {
        txt_return += `\n[无效]【${enemyInfo.name}[${currentTarget}]】已倒地`
      } else {
        // 命中计算
        // 根据双方命中闪避计算命中率
        const playerHit = Number(playerInfo.hit) || 0
        const enemyDodge = Number(enemyInfo.dodge) || 0
        const hitRate = calcHitRate(playerHit, enemyDodge)

        // 判断命中
        const randomHit = Math.random()
        if (randomHit > hitRate) {
          txt_return += `\n➥[Miss]被【${enemyInfo.name}[${currentTarget}]】闪避了！`
        } else {
          // 成功命中

          // 基础伤害
          // 默认物理伤害
          let damageType = '物理'
          const attack = Number(playerInfo.atk) || 0
          const defense = Number(enemyInfo.def) || 0
          let damage = calcNormalDamage(attack, defense)

          // 暴击率
          const playerCrit = Number(playerInfo.crit) || 0
          const enemyCritAvoid = Number(enemyInfo.crit_avoid) || 1
          const critRate = calcCritRate(playerCrit, enemyCritAvoid)

          // 判断暴击
          const randomCrit = Math.random()
          if (randomCrit > critRate) {
            damage = Math.floor(damage)
            txt_return += `\n➥`
          } else {
            // 成功暴击
            const playerCritDamage = Number(playerInfo.crit_damage) || 0
            const enemyCritResist = Number(enemyInfo.crit_resist) || 1
            const critMultiplier = calcCritMultiplier(
              playerCritDamage,
              enemyCritResist
            )
            damage = Math.floor(damage * critMultiplier)
            damage = Math.min(damage, 3 * calcNormalDamage(attack, defense)) // 最高3倍
            txt_return += `\n➥[Crit!]`
          }

          // 最终伤害显示
          txt_return += `对【${enemyInfo.name}[${currentTarget}]】造成[${damage}]点${damageType}伤害`
          // 更新目标的HP并显示变化
          // 先前hp→现在hp
          // 先确保 hp 字段为整数
          // enemyInfoKeys[enemyIndex] 是 info 的 key
          // 先读当前 hp
          let hpRaw = await ioredis.hget(enemyKey, 'hp')
          let currentEnemyHp = parseInt(hpRaw, 10)
          if (isNaN(currentEnemyHp)) currentEnemyHp = 0
          const previousHp = currentEnemyHp
          const newHp = Math.max(0, currentEnemyHp - Math.floor(damage))
          // 直接写入新血量
          await ioredis.hset(enemyKey, 'hp', newHp)
          txt_return += `\n·❤${previousHp}→${newHp}`
        }
      }
    } else if (action?.startsWith('技能')) {
      // 在此处添加技能的具体逻辑
      // 在此处添加技能的具体逻辑
      // 在此处添加技能的具体逻辑

      // 提取技能名
      const skillName = action.replace('技能:', '').trim()

      txt_return += `\n【${playerInfo.name}】施放 ${skillName}→[${currentTarget}]`

      // 查询技能信息
      const skillInfo = await skill_list.findOneValue({
        where: { name: skillName }
      })

      // 技能类型
      let damageType = skillInfo?.type

      // 物理或魔法技能
      if (damageType === '物理' || damageType === '魔法') {
        // 从Redis内存读取敌方1~6号的最新属性
        const enemyCamp = Number(camp) === 1 ? 2 : 1
        const enemyInfoKeys = Array.from(
          { length: 6 },
          (_, i) => `fantasy:battle:${battle_id}:${enemyCamp}:${i + 1}:info`
        )
        const enemyInfos = await Promise.all(
          enemyInfoKeys.map(key => ioredis.hgetall(key))
        )

        // 得到所有存活敌人的站位编号，例如 [1, 3, 5]
        const aliveEnemyPositions = enemyInfos
          .map((info, idx) => ({ hp: Number(info.hp) || 0, pos: idx + 1 }))
          .filter(obj => obj.hp > 0)
          .map(obj => obj.pos)

        // 读取技能模组
        const mod = skillInfo?.module

        // 调用技能模组函数
        let hitTargets: { target: string; damage: number }[] = []
        if (mod && aliveEnemyPositions.length > 0) {
          hitTargets = await skillMod(mod, currentTarget, aliveEnemyPositions)
        }

        // 如果没有命中任何目标
        if (hitTargets.length === 0) {
          txt_return += `\n➥[Miss]未命中`
        }
        // 遍历命中目标，计算伤害
        for (const { target, damage } of hitTargets) {
          const enemyIndex = Number(target) - 1 // 转换为0基索引
          const enemyInfo = enemyInfos[enemyIndex] || {}
          const enemyHp = Number(enemyInfo.hp) || 0
          if (enemyHp <= 0) {
            continue // 如果目标已倒地，则跳过
          }

          // 是否命中
          const playerHit = Number(playerInfo.hit) || 0
          const enemyDodge = Number(enemyInfo.dodge) || 0
          const hitRate = calcHitRate(playerHit, enemyDodge)
          const randomHit = Math.random()
          if (randomHit > hitRate) {
            txt_return += `\n➥[Miss]被【${enemyInfo.name}[${target}]】闪避了！`
            continue
          }

          // 成功命中
          // 伤害计算（根据damageType区分物理/魔法公式）
          let attack = 0
          let defense = 0
          // 技能威力
          const power = Number(skillInfo.power) || 0
          if (damageType === '物理') {
            const atk = Number(playerInfo.atk) || 0
            attack = Math.floor((atk * power) / 100) || 0
            defense = Number(enemyInfo.def) || 0
          } else if (damageType === '魔法') {
            const matk = Number(playerInfo.matk) || 0
            attack = Math.floor((matk * power) / 100) || 0
            defense = Number(enemyInfo.mdef) || 0
          }
          let baseDamage = calcNormalDamage(attack, defense)
          // 技能倍率
          baseDamage = Math.floor(baseDamage * damage) // 应用技能模组的伤害系数
          // 是否暴击
          const playerCrit = Number(playerInfo.crit) || 0
          const enemyCritAvoid = Number(enemyInfo.crit_avoid) || 1
          const critRate = calcCritRate(playerCrit, enemyCritAvoid)
          const randomCrit = Math.random()
          if (randomCrit <= critRate) {
            // 成功暴击
            const playerCritDamage = Number(playerInfo.crit_damage) || 0
            const enemyCritResist = Number(enemyInfo.crit_resist) || 1
            const critMultiplier = calcCritMultiplier(
              playerCritDamage,
              enemyCritResist
            )
            baseDamage = Math.floor(baseDamage * critMultiplier)
            baseDamage = Math.min(
              baseDamage,
              3 * calcNormalDamage(attack, defense)
            ) // 最高3倍
            txt_return += `\n➥[Crit!]`
          } else {
            // 未暴击
            txt_return += `\n➥`
          }
          // 最终伤害显示
          txt_return += `对【${enemyInfo.name}[${target}]】造成[${baseDamage}]点${damageType}伤害`
          // 更新目标的HP并显示变化
          // 先前hp→现在hp
          // 先确保 hp 字段为整数
          // enemyInfoKeys[enemyIndex] 是 info 的 key

          // 先读当前 hp
          let hpRaw = await ioredis.hget(enemyInfoKeys[enemyIndex], 'hp')
          let currentEnemyHp = parseInt(hpRaw, 10)
          if (isNaN(currentEnemyHp)) currentEnemyHp = 0

          const previousHp = currentEnemyHp
          const baseDamageInt = Math.floor(baseDamage)
          const newHp = Math.max(0, currentEnemyHp - baseDamageInt)

          // 直接写入新血量
          await ioredis.hset(enemyInfoKeys[enemyIndex], 'hp', newHp)
          txt_return += `\n·❤${previousHp}→${newHp}`
        }
      } else if (damageType === '增益') {
        // 增益技能处理
        // 增益技能处理
        // 增益技能处理
      }

      // 技能mp扣除
      const mpCost = skillInfo?.mp_cost || 0
      const currentMp = Number(playerInfo.mp) || 0
      if (currentMp >= mpCost) {
        await ioredis.hincrby(playerKey, 'mp', -mpCost)
      }

      // 技能冷却处理
      const skillCd = Number(skillInfo?.cd) || 0
      const skillCdKey = `fantasy:battle:${battle_id}:${camp}:${index}:skill_cd:${skillName}`

      // 写入本次使用技能的冷却
      if (skillCd > 0) {
        await ioredis.set(skillCdKey, skillCd)
      }
    } else {
      txt_return += `\n[${playerInfo.name}] 的指令：${action}`
    }

    // 回合末，所有冷却中技能回合数-1（自动过期，无需手动清除）
    const pattern = `fantasy:battle:${battle_id}:${camp}:${index}:skill_cd:*`
    const keys = await ioredis.keys(pattern)
    for (const cdKey of keys) {
      const cdLeft = await ioredis.ttl(cdKey)
      if (cdLeft > 1) {
        await ioredis.expire(cdKey, cdLeft - 1)
      }
    }

    // 回合末，hp与mp回复
    const hpRecovery = Math.floor(Number(playerInfo.hp_recover) || 0)
    const mpRecovery = Math.floor(Number(playerInfo.mp_recover) || 0)
    // 用set命令更新hp和mp
    // 先读当前 hp 和 mp
    let hpRaw = await ioredis.hget(playerKey, 'hp')
    let mpRaw = await ioredis.hget(playerKey, 'mp')
    let currentHp = parseInt(hpRaw, 10) + hpRecovery
    let currentMp = parseInt(mpRaw, 10) + mpRecovery
    if (isNaN(currentHp)) currentHp = 0
    if (isNaN(currentMp)) currentMp = 0
    // 确保回复后不超过上限
    currentHp = Math.min(currentHp, Number(playerInfo.hp_max))
    currentMp = Math.min(currentMp, Number(playerInfo.mp_max))
    // 写入新的hp和mp
    await ioredis.hset(playerKey, {
      hp: currentHp,
      mp: currentMp
    })

    // 清除该成员的行动指令
    await ioredis.del(actionKey)

    // 当前成员行动完毕，从队列中移除
    battleQueue.shift()

    // 回合分割线
    txt_return += `\n————————————`

    // 判断双方阵营是否全部倒地，倒地则跳出循环
    for (let camp = 1; camp <= 2; camp++) {
      const campMembers = battleInfo.filter(m => Number(m.battle_camp) === camp)
      const { allDead, winnerCamp } = await checkCampAllDead(
        battle_id,
        campMembers
      )
      if (allDead) {
        txt_return += `\n【战斗结束】`
        // 调用奖励结算函数
        await battleReward(battle_id, winnerCamp, e)
        break
      }
    }
    // 如果有阵营全部倒地，则跳出循环
    if (txt_return.includes('【战斗结束】')) {
      break
    }
  }

  // 如果没结束，回合增加
  if (!txt_return.includes('【战斗结束】')) {
    await ioredis.incr(`fantasy:battle:${battle_id}:round`)
  }

  // 如果战斗没结束，将所有redis信息同步至battle表
  for (const m of battleInfo) {
    const infoKey = `fantasy:battle:${battle_id}:${m.battle_camp}:${m.battle_index}:info`
    const infoData = await ioredis.hgetall(infoKey)
    if (Object.keys(infoData).length > 0) {
      // 更新battle表
      await battle.update(infoData, {
        where: {
          battle_id,
          battle_camp: m.battle_camp,
          battle_index: m.battle_index
        }
      })
    }
  }
  // 如果没结束，信息提示
  if (!txt_return.includes('【战斗结束】')) {
    txt_return += `\n【发送[战斗面板]查看战斗信息】`
  }

  return txt_return
}

/**
 * 计算命中率
 */
function calcHitRate(playerHit: number, enemyDodge: number): number {
  playerHit = Number(playerHit) || 0
  enemyDodge = Number(enemyDodge) || 1 // 避免除以0
  if (playerHit <= 0) return 0
  return 1 - Math.pow(0.5, playerHit / enemyDodge)
}

/**
 * 计算基础伤害
 */
function calcNormalDamage(attack: number, defense: number): number {
  attack = Number(attack) || 0
  defense = Number(defense) || 0
  if (attack + defense > 0) {
    return Math.max(0, Math.floor((attack * attack) / (attack + defense)))
  } else {
    return Math.max(0, attack)
  }
}

/**
 * 计算暴击率
 */
function calcCritRate(playerCrit: number, enemyCritAvoid: number): number {
  playerCrit = Number(playerCrit) || 0
  enemyCritAvoid = Number(enemyCritAvoid) || 1 // 避免除以0
  if (playerCrit <= 0) return 0
  return 1 - Math.pow(0.5, playerCrit / enemyCritAvoid)
}

/**
 * 计算暴击伤害倍率
 */
function calcCritMultiplier(
  playerCritDamage: number,
  enemyCritResist: number
): number {
  playerCritDamage = Number(playerCritDamage) || 0
  enemyCritResist = Number(enemyCritResist) || 1 // 避免除以0
  return 1 + playerCritDamage / enemyCritResist
}

/**
 * 技能模组，输入方式 瞄准目标 目标场地情况，返回多个命中目标与对应的伤害系数
 * [{ target: '2', damage: 1 }, { target: '5', damage: 0.5 }]
 * @param mod 技能模组
 * @param target 目标
 * @returns Promise<number, number>
 */
export async function skillMod(
  mod: string,
  target: string,
  aliveMembers
): Promise<{ target: string; damage: number }[]> {
  if (mod === '飞弹') {
    // 飞向单体目标，会被阻挡
    // 123前排对应456后排，1后面4 2后面5 3后面6
    // 目标为后排时，前排有存活成员则被阻挡，前排承受伤害，后排不受伤害
    const targetPos = Number(target)
    const isBackRow = targetPos > 3
    if (isBackRow) {
      // 后排目标
      if (aliveMembers.includes(targetPos - 3)) {
        // 前排有存活成员，飞弹被阻挡
        return [{ target: String(targetPos - 3), damage: 1.2 }]
      } else {
        // 前排无存活成员，直接命中后排目标
        return [{ target: String(targetPos), damage: 1.2 }]
      }
    } else {
      // 前排目标直接命中
      return [{ target: String(targetPos), damage: 1.2 }]
    }
  } else if (mod === '天击') {
    //对目标单体直接造成伤害
    return [{ target: String(target), damage: 1 }]
  } else if (mod === '射线') {
    // 对目标整列造成伤害，无视前后排，穿过存活目标后伤害衰减
    // 123前排对应456后排，1后面4 2后面5 3后面6
    const targetPos = Number(target)
    const targets: { target: string; damage: number }[] = []
    const isBackRow = targetPos > 3
    if (isBackRow) {
      // 后排目标
      if (aliveMembers.includes(targetPos - 3)) {
        // 前排有存活成员，射线衰减
        targets.push({ target: String(targetPos - 3), damage: 1 })
        targets.push({ target: String(targetPos), damage: 0.75 })
      } else {
        // 前排无存活成员，直接命中
        targets.push({ target: String(targetPos), damage: 1 })
      }
    } else {
      // 前排目标
      targets.push({ target: String(targetPos), damage: 1 })
      if (aliveMembers.includes(targetPos + 3)) {
        // 后排有存活成员，射线衰减
        targets.push({ target: String(targetPos + 3), damage: 0.75 })
      }
    }
    return targets
  } else if (mod === '魔荡') {
    // 对敌方前排123施放，无存活则命中对应后排
    // 123前排对应456后排，1后面4 2后面5 3后面6
    // 命中后排时伤害提升

    const targets: { target: string; damage: number }[] = []
    for (let i = 1; i <= 3; i++) {
      if (aliveMembers.includes(i)) {
        // 前排存活，命中前排
        targets.push({ target: String(i), damage: 0.75 })
      } else if (aliveMembers.includes(i + 3)) {
        // 前排倒地，后排存活，命中后排
        targets.push({ target: String(i + 3), damage: 1 })
      }
      // 如果前后排都倒地，则不命中
    }
    return targets
  } else if (mod === '波动') {
    // 对目标一整排造成伤害
    // 目标为1 2 3时，命中123；目标为4 5 6时，命中456
    // 只命中存活目标
    const targetPos = Number(target)
    const targets: { target: string; damage: number }[] = []
    if (targetPos <= 3) {
      // 目标为123
      ;[1, 2, 3].forEach(pos => {
        if (aliveMembers.includes(pos)) {
          targets.push({ target: String(pos), damage: 0.75 })
        }
      })
    } else {
      // 目标为456
      ;[4, 5, 6].forEach(pos => {
        if (aliveMembers.includes(pos)) {
          targets.push({ target: String(pos), damage: 0.75 })
        }
      })
    }
    return targets
  } else if (mod === '绽放') {
    // 对目标和周围造成伤害
    // 目标为1时，命中124；目标为2时，命中1235；目标为3时，命中236；
    // 目标为4时，命中145；目标为5时，命中2456；目标为6时，命中356
    // 命中的存活目标越多中心伤害越高
    // 中心伤害为0.4*命中数量，四周伤害为0.4
    const targetPos = Number(target)
    const targets: { target: string; damage: number }[] = []

    // 每个目标对应的受击位置
    const bloomMap: Record<number, number[]> = {
      1: [1, 2, 4],
      2: [1, 2, 3, 5],
      3: [2, 3, 6],
      4: [1, 4, 5],
      5: [2, 4, 5, 6],
      6: [3, 5, 6]
    }

    const hitList = bloomMap[targetPos] || []
    // 命中存活目标数量
    const hitAlive = hitList.filter(pos => aliveMembers.includes(pos))
    const centerAlive = aliveMembers.includes(targetPos) ? 1 : 0
    const totalAlive = hitAlive.length

    // 中心伤害为0.4*命中数量，四周伤害为0.4
    if (centerAlive) {
      targets.push({ target: String(targetPos), damage: 0.4 * totalAlive })
    }
    hitAlive.forEach(pos => {
      if (pos !== targetPos) {
        targets.push({ target: String(pos), damage: 0.4 })
      }
    })
    return targets
  } else if (mod === '全域') {
    // 对所有存活目标造成伤害
    // 123前排对应456后排，1后面4 2后面5 3后面6
    // 命中所有存活目标，伤害为0.5
    return aliveMembers.map(pos => ({ target: String(pos), damage: 0.5 }))
  }

  return []
}

/**
 * 判断某阵营是否全部倒地
 * @param battle_id 战斗id
 * @param campMembers 当前阵营成员数组
 * @returns Promise<{ allDead: boolean, winnerCamp?: number }>
 */
async function checkCampAllDead(
  battle_id: number,
  campMembers: any[]
): Promise<{ allDead: boolean; winnerCamp?: number }> {
  for (const m of campMembers) {
    const infoKey = `fantasy:battle:${battle_id}:${m.battle_camp}:${m.battle_index}:info`
    const hp = Number(await ioredis.hget(infoKey, 'hp')) || 0
    if (hp > 0) {
      return { allDead: false }
    }
  }
  // 若全部倒地，返回胜利阵营（假设只有1和2两个阵营）
  const loserCamp = campMembers[0]?.battle_camp
  const winnerCamp = loserCamp === 1 ? 2 : 1
  return { allDead: true, winnerCamp }
}

/** * 奖励结算函数
 * @param battle_id 战斗ID
 * @param winnerCamp 胜利阵营
 * @param e 事件对象
 * @return Promise<void>
 */
async function battleReward(
  battle_id: number,
  winnerCamp: number,
  e
): Promise<void> {
  // 奖励结算逻辑

  // 删除该 battle_id 下所有主key和子key
  const keys = await ioredis.keys(`fantasy:battle:${battle_id}*`)
  if (keys.length > 0) {
    await ioredis.del(...keys)
  }

  const members = await battle.findAllValues({ where: { battle_id } })
  // 筛分阵营
  const winnerMembers = members.filter(
    m => Number(m.battle_camp) === winnerCamp
  )
  const loserMembers = members.filter(m => Number(m.battle_camp) !== winnerCamp)

  // 先计算赢家奖励
  // 先计算赢家奖励
  // 先计算赢家奖励
  // 判断是否真人uid>100
  const winnerUids = winnerMembers.map(m => Number(m.uid))
  const isRealWinner = winnerUids.some(uid => uid > 100)
  // 如果是真人，初始化奖励数组，包含名称与数量
  const winnerRewards: { name: string; amount: number }[] = []

  let rewardResult = '\n【掉落奖励分配】'
  if (isRealWinner) {
    // 赢家掉落逻辑
    for (const loser of loserMembers) {
      const loserRace = loser.race || '未知'
      const loserLevel = loser.level || 0
      const affixes = loser.affixes || []

      // 1. 仅种族
      const raceDrops = await drop_list.findAllValues({
        where: { race: loserRace, affix: null }
      })

      // 2. 仅词条
      let affixDrops: any[] = []
      for (const affix of affixes) {
        const drops = await drop_list.findAllValues({
          where: { race: null, affix }
        })
        affixDrops = affixDrops.concat(drops)
      }

      // 3. 种族+词条
      let raceAffixDrops: any[] = []
      for (const affix of affixes) {
        const drops = await drop_list.findAllValues({
          where: { race: loserRace, affix }
        })
        raceAffixDrops = raceAffixDrops.concat(drops)
      }

      // 合并所有掉落项
      const allDrops = [...raceDrops, ...affixDrops, ...raceAffixDrops]

      for (const item of allDrops) {
        if (loserLevel < item.require_level) continue
        const dropChance =
          Number(
            item.base_rate + item.level_rate * (loserLevel - item.require_level)
          ) || 0
        if (Math.random() * 100 < dropChance) {
          const existingItem = winnerRewards.find(r => r.name === item.name)
          const amount = item.amount || 1
          if (existingItem) {
            existingItem.amount += amount
          } else {
            winnerRewards.push({ name: item.name, amount })
          }
        }
      }
    }

    // 读取赢家阵营
    const winnerCampMembers = await battle.findAllValues({
      where: { battle_id, battle_camp: winnerCamp }
    })
    const winnerUids = winnerCampMembers.map(m => Number(m.uid))
    // 随机分配奖励
    // 声明奖励分配映射
    const userRewardMap: { [uid: number]: { [itemName: string]: number } } = {}
    for (const reward of winnerRewards) {
      let left = reward.amount
      while (left > 0) {
        const randIdx = Math.floor(Math.random() * winnerUids.length)
        const uid = winnerUids[randIdx]
        if (!userRewardMap[uid]) userRewardMap[uid] = {}
        userRewardMap[uid][reward.name] =
          (userRewardMap[uid][reward.name] || 0) + 1
        left--
      }
    }

    // 发放奖励并输出结果
    for (const [uid, items] of Object.entries(userRewardMap)) {
      for (const [itemName, count] of Object.entries(items)) {
        await addIntoBag(Number(uid), itemName, count)
        // user表获取用户名称
        const userItem = await user.findOneValue({
          where: { uid: Number(uid) }
        })
        rewardResult += `\n【${userItem.name}】获得[${itemName}]×${count}`
      }
    }
  }

  // 更改胜方阵营状态
  for (const member of winnerMembers) {
    await setUserStatus(member.uid, 1) // 1表示自由行动
  }
  // 更改败方阵营状态
  for (const member of loserMembers) {
    await setUserStatus(member.uid, 2) // 2表示强制休息
  }
  // 删除数据表数据
  await battle.destroy({ where: { battle_id } })

  const [message] = useMessage(e)
  // 延迟5秒发送消息
  setTimeout(() => {
    message.send(format(Text(rewardResult)))
  }, 2000)
}
